﻿/*
 * Autore: Artur Tolstenco
 */

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media.Imaging;
using RecipesManager.Data;
using RecipesManager.Data.Operations;

namespace RecipesManager.MainControls.IngredientSubControls
{
    public class ShopElems
    {
        public ShopElems(string name, bool rate)
        {
            Name = name;
            Rate = rate;
        }

        public string Name { get; set; }
        public bool Rate { get; set; }

        // override object.Equals
        public override bool Equals(object obj)
        {
            if (obj == null || GetType() != obj.GetType())
            {
                return false;
            }
            return ((ShopElems)obj).Name.Equals(this.Name) && ((ShopElems)obj).Rate == this.Rate;
        }

        public override int GetHashCode()
        {
            return base.GetHashCode();
        }
    }

    /// <summary>
    /// Interaction logic for IngredientMainPane.xaml
    /// </summary>
    public partial class IngredientMainPane
    {
        public bool Editing;
        IIngredient _currentIngredient;

        readonly Dictionary<string, bool> categoriesOperations;
        readonly ObservableCollection<ShopElems> shopElems;

        private bool _fromAnotherWindow;
        public bool FromAnotherWindow
        {
            private get { return _fromAnotherWindow; }
            set
            {
                _fromAnotherWindow = value;
                if (!_fromAnotherWindow) return;
                bt_salva.ToolTip = Application.Current.FindResource("AddNewIngredientTooltip");
                bt_salva.Content = new Image { Source = new BitmapImage(new Uri("../../Icons/document-add.png", UriKind.Relative)) };
            }
        }


        public IngredientMainPane()
        {
            InitializeComponent();
            categoriesOperations = new Dictionary<string, bool>();
            shopElems = new ObservableCollection<ShopElems>();
            dg_shops.ItemsSource = shopElems;
        }

        public string CurrentIngredientName
        {
            get { return tb_nomeIngrediente.Text; }
            set
            {
                Mouse.OverrideCursor = Cursors.Wait;

                tb_nomeIngrediente.Text = value;
                MyInitialize();
                tb_nomeIngrediente.SelectionStart = tb_nomeIngrediente.Text.Length;
                tb_nomeIngrediente.Focus();
                Editing = true;

                Mouse.OverrideCursor = null;
            }
        }

        void MyInitialize()
        {
            rb_peso.IsChecked = false;
            rb_volume.IsChecked = false;
            rb_unita.IsChecked = false;
            bt_aggiungiCat.IsEnabled = false;
            bt_cancellaCat.IsEnabled = false;
            bt_aggiungiNeg.IsEnabled = false;
            bt_cancellaNeg.IsEnabled = false;
            bt_visualizzaNeg.IsEnabled = false;
            lb_categorieACuiAppartiene.Items.Clear();
            categoriesOperations.Clear();
            shopElems.Clear();


            //è il caso in cui inserisco un nuovo ingrediente
            if (tb_nomeIngrediente.Text.Equals(""))
            {
                _currentIngredient = null;
            }
            else
            {
                _currentIngredient = Manager.Ingredients[tb_nomeIngrediente.Text];

                switch (_currentIngredient.MeasureType)
                {
                    case (MeasureType.Unit):
                        rb_unita.IsChecked = true;
                        break;
                    case (MeasureType.Volume):
                        rb_volume.IsChecked = true;
                        break;
                    case (MeasureType.Weight):
                        rb_peso.IsChecked = true;
                        break;
                }

                foreach (var c in _currentIngredient.Categories)
                    lb_categorieACuiAppartiene.Items.Add(c.Name);

                foreach (var sr in _currentIngredient.ShopRatings)
                    shopElems.Add(new ShopElems(sr.Name, Rate_Converter(sr.Rating)));
                
            }

            UpdateNegoziComboBox();
            UpdateCategorieComboBox();
            bt_salva.IsEnabled = IsModified();
        }

        private static bool Rate_Converter(ShopRating rate)
        {
            return rate == ShopRating.Good;
        }

        private static ShopRating Rate_Converter(bool rate)
        {
            return rate ? ShopRating.Good : ShopRating.Bad;
        }

        private void UpdateCategorieComboBox()
        {
            cb_categorie.Items.Clear();
            if (!_fromAnotherWindow)
                cb_categorie.Items.Add(Application.Current.FindResource("ComboBoxAddNewCategorySuggestion"));
            foreach (var c in Operations.GetAddableCategoriesForIngredient(_currentIngredient == null ? "" : _currentIngredient.Name, lb_categorieACuiAppartiene.Items.Cast<string>()))
                cb_categorie.Items.Add(c.Name);
        }

        private void UpdateNegoziComboBox()
        {
            cb_negozi.Items.Clear();
            if (!_fromAnotherWindow)
                cb_negozi.Items.Add(Application.Current.FindResource("ComboBoxAddNewShopSuggestion"));
            foreach (var s in Operations.GetAddableShopsForIngredient(_currentIngredient == null ? "" : _currentIngredient.Name, shopElems.Select(s => s.Name)))
                cb_negozi.Items.Add(s.Name);
        }


        public bool IsModified()
        {
            if (_currentIngredient == null)
                return true;

            if (!tb_nomeIngrediente.Text.ToLower().Equals(_currentIngredient.Name.ToLower()))
                return true;

            if ((rb_peso.IsChecked == true && _currentIngredient.MeasureType != MeasureType.Weight) ||
                (rb_unita.IsChecked == true && _currentIngredient.MeasureType != MeasureType.Unit) ||
                (rb_volume.IsChecked == true && _currentIngredient.MeasureType != MeasureType.Volume))
                return true;

            if (_currentIngredient.Categories.Count != lb_categorieACuiAppartiene.Items.Count)
                return true;

            if (_currentIngredient.Categories.Any(category => !lb_categorieACuiAppartiene.Items.Contains(category.Name)))
                return true;

            if (_currentIngredient.ShopRatings.Count() != shopElems.Count)
                return true;

            foreach (var sr in _currentIngredient.ShopRatings)
            {
                if (!shopElems.Contains(new ShopElems(sr.Name, Rate_Converter(sr.Rating))))
                    return true;
            }

            return false;
        }

        void Cb_CategorieNegozi_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            var comboBox = sender as ComboBox;
            if (comboBox == null) return;

            if (comboBox.Equals(cb_categorie))
            {
                if (!_fromAnotherWindow)
                {
                    var selectedCategory = cb_categorie.SelectedItem as string;
                    if (selectedCategory == null)
                        return;
                    if (selectedCategory.Equals(Application.Current.FindResource("ComboBoxAddNewCategorySuggestion")))
                    {
                        var res = (new CategorySubControls.CategoryAddWindow()).ShowDialog();
                        if (res != null && res == true)
                        {
                            AddCategory(Manager.Categories.LastAdded.Name);
                            bt_salva.IsEnabled = IsModified();
                        }
                        else
                            cb_categorie.SelectedItem = null;
                    }
                }

                bt_aggiungiCat.IsEnabled = comboBox.SelectedItem != null;
            }
            else if (comboBox.Equals(cb_negozi))
            {
                if (!_fromAnotherWindow)
                {
                    var selectedShop = cb_negozi.SelectedItem as string;
                    if (selectedShop == null)
                        return;
                    if (selectedShop.Equals(Application.Current.FindResource("ComboBoxAddNewShopSuggestion")))
                    {
                        var res = (new ShopSubControls.ShopAddWindow()).ShowDialog();
                        if (res != null && res == true)
                        {
                            AddShop(Manager.Shops.LastAdded.Name);
                            bt_salva.IsEnabled = IsModified();
                        }
                        else
                            cb_negozi.SelectedItem = null;
                    }
                }
                bt_aggiungiNeg.IsEnabled = comboBox.SelectedItem != null;
            }

        }

        void Lb_CategorieACuiAppartiene_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            bt_cancellaCat.IsEnabled = lb_categorieACuiAppartiene.SelectedItem != null;
        }

        void Dg_NegoziACuiAppartiene_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            bt_cancellaNeg.IsEnabled = bt_visualizzaNeg.IsEnabled = dg_shops.SelectedItem != null;
        }

        void Bt_Aggiungi_Click(object sender, RoutedEventArgs e)
        {
            var button = sender as Button;
            if (button == null) return;

            if (button.Equals(bt_aggiungiCat))
            {
                var i = cb_categorie.SelectedItem as string;
                if (i == null)
                    return;

                AddCategory(i);
            }
            else if (button.Equals(bt_aggiungiNeg))
            {
                var i = cb_negozi.SelectedItem as string;
                if (i == null)
                    return;

                AddShop(i);
            }

            bt_salva.IsEnabled = IsModified();
        }

        void AddShop(string i)
        {
            Mouse.OverrideCursor = Cursors.Wait;

            shopElems.Add(new ShopElems(i, false));
            UpdateNegoziComboBox();

            Mouse.OverrideCursor = null;
        }

        void AddCategory(string i)
        {
            Mouse.OverrideCursor = Cursors.Wait;

            if (!categoriesOperations.ContainsKey(i))
                categoriesOperations.Add(i, true);

            lb_categorieACuiAppartiene.Items.Add(i);
            UpdateCategorieComboBox();

            Mouse.OverrideCursor = null;
        }

        void Bt_Cancella_Click(object sender, RoutedEventArgs e)
        {
            var button = sender as Button;
            if (button == null) return;

            if (button.Equals(bt_cancellaCat))
            {
                var i = lb_categorieACuiAppartiene.SelectedItem as string;
                if (i == null)
                    return;

                if (!categoriesOperations.ContainsKey(i))
                    categoriesOperations.Add(i, false);
                else
                    categoriesOperations.Remove(i);


                lb_categorieACuiAppartiene.Items.Remove(i);
                var cbSelectedItem = cb_categorie.SelectedItem as string;
                UpdateCategorieComboBox();
                cb_categorie.SelectedItem = cbSelectedItem;
            }
            else if (button.Equals(bt_cancellaNeg))
            {
                var i = dg_shops.SelectedItem as ShopElems;
                if (i == null)
                    return;

                shopElems.Remove(i);
                var cbSelectedItem = cb_negozi.SelectedItem as string;
                UpdateNegoziComboBox();
                cb_negozi.SelectedItem = cbSelectedItem;
            }

            bt_salva.IsEnabled = IsModified();
        }


        internal bool SaveCurrentIngredient()
        {
            MeasureType measureType;
            string ingredientName;

            try
            {
                if (tb_nomeIngrediente.Text.Equals((string)Application.Current.FindResource("ComboBoxAddNewIngredientSuggestion")))
                {
                    MessageBox.Show("Nome del ingrediente \"" + Application.Current.FindResource("ComboBoxAddNewIngredientSuggestion") + "\" non consentito.",
                                    (string)Application.Current.FindResource("notification_dialog_type"),
                                    MessageBoxButton.OK,
                                    MessageBoxImage.Error);
                    tb_nomeIngrediente.SelectAll();
                    tb_nomeIngrediente.Focus();
                    return false;
                }

                if ((ingredientName = tb_nomeIngrediente.Text.Trim()).Equals(""))
                {
                    MessageBox.Show("Si assicuri che il nome del ingrediente non sia vuoto.",
                                    (string)Application.Current.FindResource("notification_dialog_type"),
                                    MessageBoxButton.OK,
                                    MessageBoxImage.Error);
                    tb_nomeIngrediente.SelectAll();
                    tb_nomeIngrediente.Focus();
                    return false;
                }

                if (rb_peso.IsChecked == false && rb_unita.IsChecked == false && rb_volume.IsChecked == false)
                {
                    MessageBox.Show("Si assicuri che un'unità di misura sia selezionata.", 
                                    (string)Application.Current.FindResource("notification_dialog_type"), 
                                    MessageBoxButton.OK,
                                    MessageBoxImage.Error);
                    rb_peso.Focus();
                    return false;
                }

                if (rb_unita.IsChecked == true)
                    measureType = MeasureType.Unit;
                else if (rb_peso.IsChecked == true)
                    measureType = MeasureType.Weight;
                else
                    measureType = MeasureType.Volume;

                // se è un nuovo ingrediente
                if (_currentIngredient == null)
                {
                    _currentIngredient = Manager.Ingredients.Add(ingredientName, measureType);
                }

                _currentIngredient.Update(ingredientName, measureType, _currentIngredient.StockMeasure.Name,
                                          _currentIngredient.StockQuantity);
                tb_nomeIngrediente.Text = _currentIngredient.Name;


                foreach (var co in categoriesOperations)
                    if (co.Value)
                        _currentIngredient.Categories.Add(co.Key);
                    else
                        _currentIngredient.Categories.Remove(co.Key);

                categoriesOperations.Clear();

                // devo aspettare che ci sia poi il campo shops in ingredients

                //rimuovo i negozi che non ci sono e aggiorno i ratings

                //collection modified mi viene sollevato se tolgo il ToList
                foreach (var sr in _currentIngredient.ShopRatings.ToList())
                {
                    if (!shopElems.Select(se => se.Name).Contains(sr.Name))
                        Manager.Shops[sr.Name].IngredientRatings.Remove(_currentIngredient.Id);
                    else
                    {
                        var currentRating = shopElems.SingleOrDefault(se => se.Name.Equals(sr.Name));
                        if (currentRating != null)
                            sr.Update(Rate_Converter(currentRating.Rate));
                    }
                }

                foreach (var se in shopElems)
                {
                    if (!_currentIngredient.ShopRatings.Select(sr => sr.Name).Contains(se.Name))
                        Manager.Shops[se.Name].IngredientRatings.Add(_currentIngredient.Name, Rate_Converter(se.Rate));
                }
            } catch (Exception e)
            {
                MessageBox.Show(e.Message, (string) Application.Current.FindResource("notification_dialog_type"),
                                    MessageBoxButton.OK,
                                    MessageBoxImage.Error);
                categoriesOperations.Clear();
                return false;
            }

            bt_salva.IsEnabled = false;

            return true;
        }

        void Tb_Rb_Modified(object sender, RoutedEventArgs e)
        {
            bt_salva.IsEnabled = IsModified();
        }

        void OnChecked(object sender, RoutedEventArgs e)
        {
            bt_salva.IsEnabled = IsModified();
        }
    }
}